#ifndef pwm_h
#define pwm_h

////////////////////////////////////////////////////
//
//	PWM MODULE
//
////////////////////////////////////////////////////

//--------------Includes---------------------//
#include "TMRxConfig.h"
#include "PWM.h"


//--------------Defines---------------------//
#define TRUE 1
#define FALSE 0
#define PWMMode 0b00001111
#define TMR2PRSC 0b0000000      // 8

//--------------PROTOTYPES------------------//
void pwmInit(int frequency);
void pwmChangeDuty(int pwm1, int pwm2, int pwm3);
int calcDutyCycle(int value);
void pwmChangeFreq(int pwmFreq);
void pwmStart();
void pwmStop();

//--------------PMW.c-----------------------//
//--------------Global Variables---------------------//
unsigned int pwmDutyCycle, pwmPeriod, currentFreq;
double pwmResolution;
unsigned short currentDuty,freqChanged;

////---------Internal Functions-----------------//
//int calcDutyCycle(int value);

void pwmInit(int frequency)
{
	// 1. Set the PWM period by writing to the PR2 register.
	pwmChangeFreq(frequency);
	
	// 2. Set the PWM duty cycle by writing to the
	// CCPR1L register and CCP1CON<5:4> bits.
	pwmChangeDuty(0, 0, 0); //Initialise with duty cycle of 0.
	
	// 3. Make the CCP1,CCP2,CCP3 pins an output by clearing the
	// TRISC<1,2> and  TRISB<5> bits.
	   TRISC &= ~0b00000011;
	   TRISB &= ~0b00100000;
	   
	// 4. Set the TMR2 prescale value and enable Timer2
	// by writing to T2CON.
	
	
	
	// 5. Configure the CCP1 module for PWM operation.
		// CCP1 Mode Select bits
		  CCP1CON |= PWMMode;
		  // CCP2 Mode Select bits
		  CCP2CON |= PWMMode;
		  // CCP3 Mode Select bits
		  CCP3CON |= PWMMode;

  
  
   currentDuty=0;
   currentFreq =0;
   freqChanged =FALSE;
}

// void pwmChangeDutyCycle(int iDutyCycle)
// {    //   pwmDutyCycle = (CCPR1L:CCP1CON<5:4>)*TOSC*(TMR2PRESEL) in units of time
     // int value = iDutyCycle/(TOSC*(TMR2PRESEL));
     // CCPR2L = value>>2;               // get 8 MSB's
     // CCP2CON = (value|0b00000011);    // get 2 LSB's

// }

//void pwmChangeDuty(int pwm1, int pwm2, int pwm3)
//{  // rDutyCycle a ratio between TON/TPWM ;
//    // Input: Raw Sine values(without scaling)
//    // Scale input using PwmResolution
//    //Calculate the dutycycle for every PWM signal
//
//    int value =0;
//
//   // if((rDutyCycle != currentDuty)|| (freqChanged == TRUE))
////    {
//
//      value = calcDutyCycle(pwm1);
//      CCPR1L = value>>2;                      // get 8 MSB's
//      CCP1CON.CCP1Y  = (value|0x01) ?1 :0 ;   // get 2 LSB's
//      CCP1CON.CCP1X  = (value|0x02) ?1 :0;
//
//      // int value = (int)rDutyCycle/((PR2+1)*4);
//
//      value = calcDutyCycle(pwm2);
//      CCPR2L = value>>2;                      // get 8 MSB's
//      CCP2CON.CCP2Y  = (value|0x01) ?1 :0 ;   // get 2 LSB's
//      CCP2CON.CCP2X  = (value|0x02) ?1 :0;
//
//
//      value = calcDutyCycle(pwm3);
//      CCPR3L = value>>2;                      // get 8 MSB's
//      CCP3CON.CCP3Y  = (value|0x01) ?1 :0 ;   // get 2 LSB's
//      CCP3CON.CCP3X  = (value|0x02) ?1 :0;
//
//      // currentDuty = rDutyCycle;
//    //}
//}

void pwmChangeDuty(int pwm1, int pwm2, int pwm3)
{  // rDutyCycle a ratio between TON/TPWM ;
    // Input: Raw Sine values(without scaling)
    // Scale input using PwmResolution
    //Calculate the dutycycle for every PWM signal

   // if((rDutyCycle != currentDuty)|| (freqChanged == TRUE))
//    {


      CCPR1L = pwm1>>2;                      // get 8 MSB's
      CCP1CON.CCP1Y  = (pwm1&0x01) ?1 :0 ;   // get 2 LSB's
      CCP1CON.CCP1X  = (pwm1&0x02) ?1 :0;


      CCPR2L = pwm2>>2;                      // get 8 MSB's
      CCP2CON.CCP2Y  = (pwm2&0x01) ?1 :0 ;   // get 2 LSB's
      CCP2CON.CCP2X  = (pwm2&0x02) ?1 :0;



      CCPR3L = pwm3>>2;                      // get 8 MSB's
      CCP3CON.CCP3Y  = (pwm3&0x01) ?1 :0 ;   // get 2 LSB's
      CCP3CON.CCP3X  = (pwm3&0x02) ?1 :0;

      // currentDuty = rDutyCycle;
    //}
}

//int calcDutyCycle(int value)
//{//Return register value for the DutycCycle
// //Preconditions: PWM Resolotion has been calculated prior to this & PR2, Thus the PWM frequency is set already.
////		  the sine wave is raw.
// int afterScale = value*(((int)pow(2,pwmResolution))/2)+((((int)pow(2,pwmResolution))/2)-1);
//  return(afterScale*((PR2+1)*4)/((pow(2,pwmResolution)/2)-1));
//}
void pwmChangeFreq(int pwmFreq)
{// Preconditions: Dutycycle must be 0.
// pwmPeriod = ((PR2) + 1)*4* TOSC*(TM2PRESEL) in units of time
//    if(pwmFreq != currentFreq)
//    {
      pwmResolution = (log10((double)FOSC/(double)pwmFreq))/log10(2);

      pwmPeriod = 1/pwmFreq;
      PR2 = (pwmPeriod/(4*TOSC*(TMR2PRESEL)))-1;
     // freqChanged = TRUE;
//      pwmChangeDuty(currentDuty);          //After frequency changes keep the same dutycycle
//      currentFreq = pwmFreq;
   // }
    // freqChanged = FALSE;                      //Reset freqChanged to initial value; false;

}
void pwmStart()
{ //Start Timer2 
  Timer2_Start();
  //Start Timer1
}
void pwmStop()
{//Stop Timer2
 Timer2_Stop();
 //Stop Timer1
}
#endif